package com.slz.crm.server.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.slz.crm.common.enumeration.PermissionOperates;
import com.slz.crm.common.excellistener.CustomerContactListener;
import com.slz.crm.common.exiception.BaseException;
import com.slz.crm.common.untils.AOTOExcelUntil;
import com.slz.crm.common.untils.BaseUnit;
import com.slz.crm.common.untils.ForeignKeyDeleteUtil;
import com.slz.crm.pojo.dto.CustomerContactDTO;
import com.slz.crm.pojo.entity.CustomerContactEntity;
import com.slz.crm.pojo.entity.RoleEntity;
import com.slz.crm.pojo.entity.RolePermissionsEntity;
import com.slz.crm.pojo.entity.UserEntity;
import com.slz.crm.pojo.excel.CustomerContactExcel;
import com.slz.crm.pojo.excel.GetCustomerContactExcel;
import com.slz.crm.pojo.vo.CustomerContactVO;
import com.slz.crm.pojo.vo.GroupResultVO;
import com.slz.crm.pojo.vo.UserVO;
import com.slz.crm.server.annotation.Privacy;
import com.slz.crm.server.constant.MessageConstant;
import com.slz.crm.server.mapper.*;
import com.slz.crm.server.service.ContractOrderItemService;
import com.slz.crm.server.service.CustomerContactService;
import com.slz.crm.server.service.SalesOpportunityService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

@Service
public class CustomerContactServiceImpl extends ServiceImpl<CustomerContactMapper, CustomerContactEntity> implements CustomerContactService {

    @Autowired
    private CustomerCompanyMapper customerCompanyMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CustomerContactMapper customerContactMapper;

    @Autowired
    private ForeignKeyDeleteUtil foreignKeyDeleteUtil;

    @Autowired
    private AOTOExcelUntil aotoExcelUntil;

    @Autowired
    private SalesOpportunityService salesOpportunityService;

    @Autowired
    private ContractOrderItemService contractOrderItemService;
    @Autowired
    private RolePermissionsMapper rolePermissionsMapper;
    @Autowired
    private RoleMapper roleMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int list(MultipartFile file) {

        if (file.isEmpty()) {
            throw new BaseException(MessageConstant.FILE_IS_NULL);
        }
        List<CustomerContactEntity> dataList;

        try {
            CustomerContactListener listener = new CustomerContactListener(customerCompanyMapper);
            EasyExcel.read(file.getInputStream(), CustomerContactExcel.class, listener).sheet().doRead();
            dataList = listener.getDataList();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        saveBatch(dataList);
        return dataList.size();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateList(List<CustomerContactDTO> list) {

        Long creatorId = BaseUnit.getCurrentId();

        List<CustomerContactEntity> dataList = new ArrayList<>();

        list.forEach(data -> {
            CustomerContactEntity entity = new CustomerContactEntity();
            BeanUtils.copyProperties(data, entity);
            entity.setCreatorId(creatorId);
            dataList.add(entity);
        });

        saveBatch(dataList);

        return list.size();
    }

    @Override
    public int insert(CustomerContactDTO customerContactDTO) {

        Long creatorId = BaseUnit.getCurrentId();
        CustomerContactEntity entity = new CustomerContactEntity();
        BeanUtils.copyProperties(customerContactDTO, entity);
        entity.setCreatorId(creatorId);
        save(entity);

        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteOrRecoverByIds(List<Long> idList, boolean isDelete) {

        List<CustomerContactEntity> dataList = new ArrayList<>();

        idList.forEach(id -> {
            CustomerContactEntity entity = getById(id);
            entity.setIsDeleted(isDelete);
            dataList.add(entity);
        });

        updateBatchById(dataList);

        // 如果是删除操作，级联删除相关数据
        if (isDelete) {
            // 级联删除相关销售机会
            salesOpportunityService.cascadeDeleteByContactIds(idList);
        }

        return dataList.size();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteByIds(List<Long> idList) {

        if (idList == null || idList.isEmpty()) {
            throw new BaseException(MessageConstant.ID_LIST_IS_NULL);
        }

        // 1. 删除所有关联的外键数据（使用配置的关联关系）
        // 资源类型：2-联系人（对应DataShareEntity的resourceType）
        foreignKeyDeleteUtil.deleteCascade(CustomerContactEntity.class, idList, 2);

        // 2. 物理删除联系人本身
        return customerContactMapper.deleteBatchIds(idList);
    }


    @Privacy
    public List<CustomerContactVO> getContactByCompanyId(Long id) {
        if (id == null) {
            throw new BaseException(MessageConstant.COMPANY_DATA_IS_NULL);
        }

        LambdaQueryWrapper<CustomerContactEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomerContactEntity::getCompanyId, id)
                .eq(CustomerContactEntity::getIsDeleted, false);

        List<CustomerContactEntity> customerContactEntityList = baseMapper.selectList(queryWrapper);
        if (customerContactEntityList.isEmpty()) {
            throw new BaseException(MessageConstant.DATA_IS_NULL);
        }

        List<CustomerContactVO> customerContactVOList = new ArrayList<>();
        customerContactEntityList.forEach(entity -> {
            CustomerContactVO vo = new CustomerContactVO();
            BeanUtils.copyProperties(entity, vo);
            customerContactVOList.add(vo);
        });

        return customerContactVOList;
    }

    @Override
    public byte[] getExcel() {

        List<CustomerContactExcel> list = new ArrayList<>();

        List<CustomerContactEntity> entities = list(new LambdaQueryWrapper<CustomerContactEntity>()
                .eq(CustomerContactEntity::getIsDeleted, false));

        if (entities.isEmpty()) {
            throw new BaseException(MessageConstant.DATA_IS_NULL);
        }

        entities.forEach(entity -> {
            CustomerContactExcel excel = new CustomerContactExcel();
            BeanUtils.copyProperties(entity, excel);

            //公司名称、性别
            excel.setCreateName(userMapper.selectById(entity.getCreatorId()).getRealName());
            excel.setGender(entity.getGender() == 0 ? "男" : "女");
            excel.setCompanyName(customerCompanyMapper.selectById(entity.getCompanyId()).getCompanyName());

            list.add(excel);
        });

        return aotoExcelUntil.AOTOExcelByStream(list, "客户联系人");
    }

    @Override
    @Privacy
    public Page<CustomerContactVO> getCustomerContactByCompanyId(Integer pageNum, Integer pageSize) {
        if (pageNum == null || pageSize == null) {
            throw new BaseException(MessageConstant.PAGE_DATA_IS_NULL);
        }
        Page<CustomerContactEntity> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<CustomerContactEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomerContactEntity::getIsDeleted, false);
        baseMapper.selectPage(page, queryWrapper);
        List<CustomerContactEntity> records = page.getRecords();
        List<CustomerContactVO> customerContactVOList = new ArrayList<>();
        records.forEach(entity -> {
            CustomerContactVO vo = new CustomerContactVO();
            BeanUtils.copyProperties(entity, vo);
            customerContactVOList.add(vo);
        });

        Page<CustomerContactVO> ans = new Page<>(pageNum, pageSize);
        BeanUtils.copyProperties(page, ans);
        ans.setRecords(customerContactVOList);

        return ans;
    }

    @Override
    @Privacy
    public Page<CustomerContactVO> search(CustomerContactDTO customerContactDTO, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<CustomerContactEntity> queryWrapper = new LambdaQueryWrapper<>();
        if (customerContactDTO.getCompanyId() != null) {
            queryWrapper.eq(CustomerContactEntity::getCompanyId, customerContactDTO.getCompanyId());
        }
        if (customerContactDTO.getName() != null && !customerContactDTO.getName().isEmpty()) {
            queryWrapper.like(CustomerContactEntity::getName, customerContactDTO.getName());
        }
        if (customerContactDTO.getPosition() != null && !customerContactDTO.getPosition().isEmpty()) {
            queryWrapper.like(CustomerContactEntity::getPosition, customerContactDTO.getPosition());
        }
        if (customerContactDTO.getPhone() != null && !customerContactDTO.getPhone().isEmpty()) {
            queryWrapper.like(CustomerContactEntity::getPhone, customerContactDTO.getPhone());
        }
        if (customerContactDTO.getMobile() != null && !customerContactDTO.getMobile().isEmpty()) {
            queryWrapper.like(CustomerContactEntity::getMobile, customerContactDTO.getMobile());
        }
        if (customerContactDTO.getEmail() != null && !customerContactDTO.getEmail().isEmpty()) {
            queryWrapper.like(CustomerContactEntity::getEmail, customerContactDTO.getEmail());
        }
        if (customerContactDTO.getGender() != null && customerContactDTO.getGender() != 0) {
            queryWrapper.eq(CustomerContactEntity::getGender, customerContactDTO.getGender());
        }
        if (customerContactDTO.getRemark() != null && !customerContactDTO.getRemark().isEmpty()) {
            queryWrapper.like(CustomerContactEntity::getRemark, customerContactDTO.getRemark());
        }
        if (customerContactDTO.getIsDeleted() != null) {
            queryWrapper.eq(CustomerContactEntity::getIsDeleted, customerContactDTO.getIsDeleted());
        } else {
            queryWrapper.eq(CustomerContactEntity::getIsDeleted, false);
        }
        Page<CustomerContactEntity> page = new Page<>(pageNum, pageSize);
        baseMapper.selectPage(page, queryWrapper);
        List<CustomerContactEntity> customerContactEntityList = page.getRecords();
        List<CustomerContactVO> customerContactVOList = new ArrayList<>();
        customerContactEntityList.forEach(entity -> {
            CustomerContactVO vo = new CustomerContactVO();
            BeanUtils.copyProperties(entity, vo);
            customerContactVOList.add(vo);
        });

        Page<CustomerContactVO> ans = new Page<>(pageNum, pageSize);
        BeanUtils.copyProperties(page, ans);
        ans.setRecords(customerContactVOList);

        return ans;
    }

    @Override
    @Privacy
    public CustomerContactVO get(Long id) {
        //获取联系人
        CustomerContactEntity entity = getOne(new LambdaQueryWrapper<CustomerContactEntity>()
                .eq(CustomerContactEntity::getId, id)
                .eq(CustomerContactEntity::getIsDeleted, false));
        if (entity == null) {
            return null;
        }
        CustomerContactVO vo = new CustomerContactVO();
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }


    @Override
    public GroupResultVO groupByCustomerContact(String field) {

        // 检查字段是否有效
        if (!Arrays.asList("companyId", "gender", "creatorId", "position").contains(field)) {
            throw new BaseException(MessageConstant.GROUP_FIELD_IS_ERROR);
        }

        LambdaQueryWrapper<CustomerContactEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomerContactEntity::getIsDeleted, false);

        List<CustomerContactEntity> entities = customerContactMapper.selectList(queryWrapper);
        Map<Object, List<CustomerContactVO>> groupMap = new HashMap<>();

        // 按不同字段分组
        for (CustomerContactEntity entity : entities) {
            CustomerContactVO vo = new CustomerContactVO();
            BeanUtils.copyProperties(entity, vo);

            Object groupKey = getGroupKey(entity, field);
            if (groupKey == null) {
                continue;
            }

            groupMap.computeIfAbsent(groupKey, k -> new ArrayList<>()).add(vo);
        }

        GroupResultVO resultVO = new GroupResultVO();
        resultVO.setGroupField(field);
        resultVO.setGroupData(groupMap);


        return resultVO;
    }

    private Object getGroupKey(CustomerContactEntity entity, String field) {
        return switch (field) {
            case "companyId" -> entity.getCompanyId();
            case "gender" -> entity.getGender();
            case "creatorId" -> entity.getCreatorId();
            case "position" -> entity.getPosition();
            default -> null;
        };
    }

    @Override
    public byte[] template() {
        List<GetCustomerContactExcel> customerContactExcels = new ArrayList<>();
        customerContactExcels.add(new GetCustomerContactExcel());
        return aotoExcelUntil.AOTOExcelByStream(customerContactExcels, "customer_contact_template.xlsx");
    }

    @Override
    public void cascadeDeleteByCompanyId(Long companyId) {
        LambdaUpdateWrapper<CustomerContactEntity> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(CustomerContactEntity::getCompanyId, companyId)
                .eq(CustomerContactEntity::getIsDeleted, false)
                .set(CustomerContactEntity::getIsDeleted, true);
        update(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer logicalDeleteById(Long id) {
        return foreignKeyDeleteUtil.logicalDeleteByCascade(CustomerContactEntity.class, id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer batchLogicalDeleteByIds(List<Long> idList) {
        if (idList == null || idList.isEmpty()) {
            throw new BaseException(MessageConstant.ID_LIST_IS_NULL);
        }

        Integer count = 0;
        for (Long id : idList) {
            count += logicalDeleteById(id);
        }
        return count;
    }

    @Override
    public List<UserVO> getAuditor() {

        Long id = PermissionOperates.SalesOperate.APPROVE_STAGE_ADVANCE.getId();

        List<RolePermissionsEntity> rolePermissionsEntities = rolePermissionsMapper
                .selectList(new LambdaQueryWrapper<RolePermissionsEntity>()
                        .eq(RolePermissionsEntity::getPermissionsId, id));
        List<Long> list = rolePermissionsEntities.stream().map(RolePermissionsEntity::getRoleId).toList();

        Map<Long, String> roleNameMap = new HashMap<>();

        roleMapper.selectList(new LambdaQueryWrapper<RoleEntity>().in(RoleEntity::getId, list)).forEach(role -> {
            roleNameMap.put(role.getId(), role.getRoleName());
        });

        LambdaQueryWrapper<UserEntity> in = new LambdaQueryWrapper<UserEntity>();

        if (!list.isEmpty()) {
            in.in(UserEntity::getRoleId, list);
        } else {
            in.eq(UserEntity::getRoleId, 0);
        }

        List<UserEntity> userEntities = userMapper.selectList(in);
        List<UserVO> ans = new ArrayList<>();

        userEntities.forEach(userEntity -> {
            UserVO vo = new UserVO();
            BeanUtils.copyProperties(userEntity, vo);
            vo.setRoleName(roleNameMap.get(vo.getRoleId()));
            ans.add(vo);
        });

        return ans;
    }
}
